﻿namespace PageTypeBuilder.SortOrderChecker
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;

    public class SortOrderFixer
    {
        public void Fix(string assemblyFolderPath, string projectFolderPath)
        {
            DirectoryInfo assemblyFolder = new DirectoryInfo(assemblyFolderPath);
            DirectoryInfo projectFolder = new DirectoryInfo(projectFolderPath);

            if (!assemblyFolder.Exists)
                throw new Exception(string.Format("The path '{0}' does not exist.", assemblyFolderPath));

            if (!projectFolder.Exists)
                throw new Exception(string.Format("The path '{0}' does not exist.", projectFolderPath));

            SortOrderChecker.LoadAssemblies(assemblyFolder);

            List<Definition> pageTypes = SortOrderChecker.GetDefinitions().ToList();
            List<Type> pageTypeTypes = GetAllTypesAndBaseTypesInCorrectHeirarchy(pageTypes.Select(c => c.Type), false).ToList();
            List<Type> propertyGroups = GetPropertyGroups(pageTypeTypes);
            List<Type> propertyGroupTypes = GetAllTypesAndBaseTypesInCorrectHeirarchy(propertyGroups, true).ToList();

            List<FixData> standardData = GetData(pageTypeTypes, false);
            List<FixData> propertyGroupData = GetData(propertyGroupTypes, true);

            Console.Clear();

            ChangeSortOrders(standardData, false);
            ChangeSortOrders(propertyGroupData, true);

            FixFiles(projectFolder, standardData, "PageTypeProperty", "SortOrder");
            FixFiles(projectFolder, propertyGroupData, "PageTypeProperty", "SortOrder");

            // now sort out start sort order from for property groups?
            FixStartSortOrderFromForPropertyGroups(projectFolder, pageTypeTypes, standardData, propertyGroupData);

            Console.WriteLine("Complete");
            Console.ReadLine();
        }

        public void GenerateSql(string assemblyFolderPath, string outputFilePath)
        {
            DirectoryInfo assemblyFolder = new DirectoryInfo(assemblyFolderPath);

            if (!assemblyFolder.Exists)
                throw new Exception(string.Format("The path '{0}' does not exist.", assemblyFolderPath));

            if (string.IsNullOrEmpty(outputFilePath))
                throw new Exception("You must speicfy an output file path.");

            SortOrderChecker.LoadAssemblies(assemblyFolder);

            List<Definition> pageTypeDefinitions = SortOrderChecker.GetDefinitions().ToList();

            StringBuilder sqlBuilder = new StringBuilder();
            sqlBuilder.AppendLine("DECLARE @PageTypeId int");
            //sqlBuilder.AppendLine("DECLARE @PageDefinitionId int");
            sqlBuilder.AppendLine();

            // RESET SORT ORDERS, NEED TO TEST WITH PROPERTY GROUPS
            foreach (Definition definition in pageTypeDefinitions)
            {
                bool newPageTypeDefinition = true;
                bool sqlAppended = false;

                // page type name, property name, sort order
                Dictionary<string, Data> sortOrders = new Dictionary<string, Data>();

                // standard properties
                List<PropertyInfo> properties = SortOrderChecker.GetPageTypeProperties(definition.Type).ToList();

                foreach (PropertyInfo property in properties)
                {
                    string name = property.Name;
                    object attribute = SortOrderChecker.GetPageTypePropertyAttribute(property);
                    AppendSql(ref newPageTypeDefinition, sqlBuilder, definition.PageTypeName, name);
                    sqlAppended = true;

                    Data data = new Data
                    {
                        Attribute = attribute,
                        PropertyGroupAttribute = null,
                        PropertyGroupName = string.Empty
                    };

                    sortOrders.Add(name, data);
                }

                // property group properties
                foreach (PropertyInfo property in SortOrderChecker.GetPropertyGroupProperties(definition.Type))
                {
                    properties = SortOrderChecker.GetPageTypeProperties(property.PropertyType).ToList();

                    foreach (PropertyInfo subProperty in properties)
                    {
                        string name = string.Format("{0}-{1}", property.Name, subProperty.Name);
                        object attribute = SortOrderChecker.GetPageTypePropertyAttribute(property);
                        //object propertyGroupAttribute = SortOrderChecker.GetPageTypePropertyGroupAttribute(property);
                        //string propertyGroupName = property.Name;
                        AppendSql(ref newPageTypeDefinition, sqlBuilder, definition.PageTypeName, name);
                        sqlAppended = true;

                        Data data = new Data
                        {
                            Attribute = attribute,
                            PropertyGroupAttribute = null,
                            PropertyGroupName = string.Empty
                        };

                        sortOrders.Add(name, data);
                    }
                }

                foreach (var data in sortOrders)
                {
                    string propertyName = data.Key;
                    int fieldOrder = data.Value.GetSortOrder();

                    if (fieldOrder <= 0)
                        continue;

                    AppendSql(ref newPageTypeDefinition, sqlBuilder, definition.PageTypeName, propertyName, fieldOrder);
                    sqlAppended = true;
                }

                if (sqlAppended)
                    sqlBuilder.AppendLine("END");
            }

            File.WriteAllText(outputFilePath, sqlBuilder.ToString());
            Console.WriteLine("Sql wrote to '{0}.", outputFilePath);
        }

        private void AppendSql(ref bool newPageTypeDefinition, StringBuilder sqlBuilder, string pageTypeName, string propertyName, int fieldOrder = 0)
        {
            //sqlBuilder.AppendLine();

            if (newPageTypeDefinition)
            {
                sqlBuilder.AppendLine(string.Format("SELECT @PageTypeId = [pkID] FROM [tblPageType] WHERE [Name] = '{0}'", pageTypeName));
                sqlBuilder.AppendLine();
                sqlBuilder.AppendLine("IF @PageTypeId IS NOT NULL");
                sqlBuilder.AppendLine("BEGIN");
            }
            //sqlBuilder.AppendLine(string.Format("\t-- Reset field order on page type '{0}' property '{1}'.", pageTypeName, propertyName));
            //sqlBuilder.AppendLine(string.Format("\tSELECT @PageDefinitionId = [pkID] FROM [tblPageDefinition] WHERE [Name] = '{0}' AND [fkPageTypeId] = @PageTypeId", propertyName));
            //sqlBuilder.AppendLine();
            //sqlBuilder.AppendLine("\tIF @PageDefinitionId IS NOT NULL");
            //sqlBuilder.AppendLine("\tBEGIN");
            //sqlBuilder.AppendLine(string.Format("\t\tUPDATE [tblPageDefinition] SET [FieldOrder] = {0} WHERE [pkID] = @PageDefinitionId", fieldOrder));
            sqlBuilder.AppendLine(string.Format("\t\tUPDATE [tblPageDefinition] SET [FieldOrder] = {0} WHERE [Name] = '{1}' AND [fkPageTypeId] = @PageTypeId", fieldOrder, propertyName));
            //sqlBuilder.AppendLine("\tEND");
            newPageTypeDefinition = false;
        }

        private void FixStartSortOrderFromForPropertyGroups(DirectoryInfo projectFolder, List<Type> pageTypeTypes, List<FixData> standardData, List<FixData> propertyGroupData)
        {
            foreach (Type pageTypeType in pageTypeTypes)
            {
                List<PropertyInfo> propertyGroupProperties = SortOrderChecker.GetPropertyGroupProperties(pageTypeType).ToList();

                if (propertyGroupProperties.Count == 0)
                    continue;

                // get all existing sort orders for standard properties
                List<int> pageTypePropertySortOrders = new List<int>();
                Type type = pageTypeType;

                while (type.FullName != "PageTypeBuilder.TypedPageData")
                {
                    FixData fixData = standardData.First(c => c.Type == type);
                    pageTypePropertySortOrders.AddRange(fixData.FixPropertyData.Select(c => c.SortOrder).Distinct().ToList());
                    type = type.BaseType;
                }

                List<int> propertyGroupSortOrders = new List<int>();

                foreach (PropertyInfo propertyGroupProperty in propertyGroupProperties)
                {
                    object attribute = SortOrderChecker.GetPageTypePropertyGroupAttribute(propertyGroupProperty);
                    int startSortOrderFrom = attribute.GetStartSortOrderFrom();

                    if (startSortOrderFrom < 0)
                        startSortOrderFrom = 0;

                    List<int> sortOrders = new List<int>();
                    sortOrders.AddRange(pageTypePropertySortOrders);
                    sortOrders.AddRange(propertyGroupSortOrders);

                    // sort orders needs to contain other property group properties too
                    FixData fixData = propertyGroupData.First(c => c.Type == propertyGroupProperty.PropertyType);
                    int newStartSortOrderFrom = GetNextStartSortOrderFrom(startSortOrderFrom, sortOrders, fixData, propertyGroupData);

                    // add sort orders to property group sort orders
                    type = propertyGroupProperty.PropertyType;

                    while (type.FullName != "PageTypeBuilder.PageTypePropertyGroup")
                    {
                        FixData currentFixData = propertyGroupData.FirstOrDefault(c => c.Type == type);
                        propertyGroupSortOrders.AddRange(currentFixData.FixPropertyData.Select(c => newStartSortOrderFrom + c.SortOrder).Distinct().ToList());
                        type = type.BaseType;
                    }

                    if (newStartSortOrderFrom == startSortOrderFrom)
                        continue;

                    FixData newFixData = new FixData { Type = pageTypeType };

                    newFixData.FixPropertyData.Add(new FixPropertyData
                    {
                        Changed = true,
                        Property = propertyGroupProperty,
                        SortOrder = newStartSortOrderFrom,
                        Type = pageTypeType
                    });

                    FixFiles(projectFolder, new List<FixData> { newFixData }, "PageTypePropertyGroup", "StartSortOrderFrom");
                }
            }
        }

        private int GetNextStartSortOrderFrom(int startSortOrderFrom, List<int> existingSortOrders,
            FixData fixData, List<FixData> allFixData)
        {
            int newStartSortOrderFrom = startSortOrderFrom;

            List<int> sortOrders = GetSortOrders(newStartSortOrderFrom, fixData, allFixData);

            while (AreThereConflictingSortOrders(existingSortOrders, sortOrders))
            {
                newStartSortOrderFrom++;
                sortOrders = GetSortOrders(newStartSortOrderFrom, fixData, allFixData);
            }

            return newStartSortOrderFrom;
        }

        private bool AreThereConflictingSortOrders(List<int> existingSortOrders, List<int> sortOrders)
        {
            foreach (int sortOrder in sortOrders)
            {
                if (existingSortOrders.Any(c => c == sortOrder))
                    return true;
            }

            return false;
        }

        private List<int> GetSortOrders(int startSortOrderFrom, FixData fixData, List<FixData> allFixData)
        {
            List<int> sortOrders = new List<int>();
            Type type = fixData.Type;

            while (type.FullName != "PageTypeBuilder.PageTypePropertyGroup")
            {
                FixData currentFixData = allFixData.FirstOrDefault(c => c.Type == type);
                sortOrders.AddRange(currentFixData.FixPropertyData.Select(c => startSortOrderFrom + c.SortOrder).Distinct().ToList());
                type = type.BaseType;
            }

            return sortOrders;
        }

        private void ChangeSortOrders(List<FixData> data, bool propertyGroup)
        {
            foreach (FixData dataItem in data)
            {
                Console.WriteLine();
                Console.WriteLine("********************************************");
                Console.WriteLine("- Anaylizing page type properties in {0} class {1}.", propertyGroup ? "property group" : "page type ", dataItem.Type.FullName);
                string baseTypeName = propertyGroup ? "PageTypeBuilder.PageTypePropertyGroup" : "PageTypeBuilder.TypedPageData";

                List<int> baseSortOrders = GetAllBaseSortOrdersFromType(data, dataItem.Type);
                List<int> distinctSortOrders = dataItem.FixPropertyData.Select(c => c.SortOrder).Distinct().ToList();

                foreach (int sortOrder in distinctSortOrders)
                {
                    List<FixPropertyData> fixPropertyDatas = new List<FixPropertyData>();
                    foreach (FixPropertyData item in dataItem.FixPropertyData.Where(c => c.SortOrder == sortOrder).ToList())
                    {
                        if (dataItem.Type.BaseType.FullName != baseTypeName)
                        {
                            if (SortOrderChecker.GetPageTypeProperties(dataItem.Type.BaseType).Any(p => p.Name == item.Property.Name))
                                continue;
                        }

                        fixPropertyDatas.Add(item);
                    }

                    bool skip = sortOrder > 0 && fixPropertyDatas.Count > 0 && !baseSortOrders.Contains(sortOrder);

                    if (skip)
                        fixPropertyDatas = fixPropertyDatas.Skip(1).ToList();

                    foreach (FixPropertyData item in fixPropertyDatas)
                    {
                        int currentSortOrder = item.SortOrder;
                        int newSortOrder = GetNextNumber(baseSortOrders, dataItem.FixPropertyData.Select(c => c.SortOrder).ToList(), currentSortOrder);

                        if (newSortOrder == currentSortOrder)
                            continue;

                        Console.WriteLine("- Determined that sort order for property {0} needs to change from {1} to {2}.",
                            item.Property.Name, currentSortOrder, newSortOrder);

                        item.SortOrder = newSortOrder;
                        item.Changed = true;
                    }
                }
            }
        }

        private int GetNextNumber(IEnumerable<int> baseSortOrders, List<int> currentSortOrders, int currentSortOrder)
        {
            List<int> allSortOrders = new List<int>();
            allSortOrders.AddRange(baseSortOrders);

            int index = currentSortOrders.IndexOf(currentSortOrder);
            if (index != -1)
                currentSortOrders.RemoveAt(index);

            allSortOrders.AddRange(currentSortOrders);

            if (currentSortOrder <= 0)
            {
                if (allSortOrders.Count == 0)
                    return 10;

                return allSortOrders.Max() + 1;
            }

            if (allSortOrders.Count(c => c == currentSortOrder) > 0)
            {
                currentSortOrder++;

                while (allSortOrders.Count(c => c == currentSortOrder) > 0)
                    currentSortOrder++;

                return currentSortOrder;
            }

            return currentSortOrder;
        }

        private List<FixData> GetData(IEnumerable<Type> types, bool propertyGroup)
        {
            List<FixData> data = new List<FixData>();

            foreach (Type type in types)
            {
                FixData fixDataItem = new FixData { Type = type };
                string baseType = propertyGroup ? "PageTypeBuilder.PageTypePropertyGroup" : "PageTypeBuilder.TypedPageData";

                List<PropertyInfo> properties = SortOrderChecker.GetPageTypeProperties(type).ToList();

                foreach (PropertyInfo property in properties)
                {
                    if (fixDataItem.Type.BaseType.FullName != baseType)
                    {
                        if (SortOrderChecker.GetPageTypeProperties(fixDataItem.Type.BaseType).Any(p => p.Name == property.Name))
                            continue;
                    }

                    fixDataItem.FixPropertyData.Add(new FixPropertyData
                    {
                        Type = type,
                        Property = property,
                        SortOrder = property.GetSortOrder(),
                        Changed = false
                    });
                }

                data.Add(fixDataItem);
            }

            return data;
        }

        private List<int> GetAllBaseSortOrdersFromType(List<FixData> data, Type type)
        {
            int index = data.Select(d => d.Type).ToList().IndexOf(type);

            if (index == 0)
                return new List<int>();

            List<int> sortOrders = new List<int>();

            for (int i = 0; i < index; i++)
                sortOrders.AddRange(data[i].FixPropertyData.Select(c => c.SortOrder));

            return sortOrders.Distinct().ToList();
        }

        private List<Type> GetPropertyGroups(IEnumerable<Type> pageTypeTypes)
        {
            List<Type> propertyGroups = new List<Type>();

            Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().Where(c => c.GetName().Name == "PageTypeBuilder").FirstOrDefault();
            Type propertyGroupType = null;

            if (assembly != null)
                propertyGroupType = assembly.GetType("PageTypeBuilder.PageTypePropertyGroup");

            if (propertyGroupType != null)
            {
                foreach (Type pageTypeType in pageTypeTypes)
                {
                    // should get property groups
                    IEnumerable<PropertyInfo> properties = SortOrderChecker.GetPropertyGroupProperties(pageTypeType);

                    foreach (PropertyInfo property in properties)
                    {
                        if (!property.PropertyType.IsSubclassOf(propertyGroupType))
                            continue;

                        propertyGroups.Add(property.PropertyType);
                    }
                }
            }

            return propertyGroups;
        }

        private IEnumerable<Type> GetAllTypesAndBaseTypesInCorrectHeirarchy(IEnumerable<Type> definitions, bool propertyGroup)
        {
            List<Type> types = new List<Type>();

            string baseTypeName = propertyGroup ? "PageTypeBuilder.PageTypePropertyGroup" : "PageTypeBuilder.TypedPageData";

            foreach (Type definition in definitions)
            {
                List<Type> currentTypes = new List<Type>();
                Type currentType = definition;
                currentTypes.Add(currentType);

                while (currentType.BaseType.FullName != baseTypeName)
                {
                    currentTypes.Add(currentType.BaseType);
                    currentType = currentType.BaseType;
                }

                currentTypes.Reverse();

                foreach (Type type in currentTypes)
                    AddType(types, type);
            }

            return types;
        }

        private void AddType(IList<Type> types, Type type)
        {
            if (types.Contains(type))
                return;

            if (types.Contains(type.BaseType))
            {
                int index = types.IndexOf(type.BaseType);

                if (index == types.Count - 1)
                    types.Add(type);
                else
                    types.Insert(index + 1, type);
            }
            else
                types.Add(type);
        }

        private void FixFiles(DirectoryInfo projectFolder, List<FixData> data,
            string attributeName, string sortOrderPropertyName)
        {
            FileInfo projectFile = projectFolder.GetFiles("*.csproj").FirstOrDefault();

            if (projectFile == null)
                throw new Exception("Could not find a .csproj file.");

            string rootNamespace = GetRootNameSpace(projectFile);

            foreach (FixData dataItem in data)
            {
                if (!dataItem.FixPropertyData.Any(c => c.Changed))
                    continue;

                string path = FindFile(projectFolder, dataItem.Type, rootNamespace);

                if (string.IsNullOrEmpty(path))
                {
                    Console.WriteLine("* Could not find file for type '{0}", dataItem.Type.FullName);
                    continue;
                }

                Console.WriteLine();
                Console.WriteLine("****************************************");
                Console.WriteLine("- Fixing file '{0}'", path);

                foreach (FixPropertyData item in dataItem.FixPropertyData.Where(c => c.Changed))
                {
                    string propertyName = item.Property.Name;
                    string sortOrder = item.SortOrder.ToString();
                    string fileContent = File.ReadAllText(path);

                    int index = fileContent.IndexOf(string.Format(" class {0}", dataItem.Type.Name));

                    if (index == -1)
                    {
                        Console.WriteLine("* Could not find '{0}' in file '{1}'.", string.Format(" class {0}", dataItem.Type.Name), path);
                        continue;
                    }

                    string originalClassContent = fileContent.Substring(index);
                    index = FindProperty(originalClassContent, propertyName);

                    if (index == -1)
                        continue;

                    string originalPropertyContent = originalClassContent.Substring(0, index);
                    string attributeSearchFor = string.Format("[{0}(", attributeName);
                    int attributeIndex = originalPropertyContent.LastIndexOf(attributeSearchFor);

                    if (attributeIndex == -1)
                        continue;

                    originalPropertyContent = originalPropertyContent.Substring(attributeIndex, index - attributeIndex);
                    string newContent = originalPropertyContent;
                    index = newContent.IndexOf(sortOrderPropertyName);

                    if (index == -1)
                    {
                        string firstPart = newContent.Substring(0, attributeSearchFor.Length);
                        string lastPart = newContent.Substring(attributeSearchFor.Length);
                        newContent = firstPart + sortOrderPropertyName + " = " + sortOrder + ", " + lastPart;
                        Console.WriteLine("  Setting sort order for property '{0}' to {1}", propertyName, sortOrder);
                    }
                    else
                    {
                        string temp = newContent.Substring(index);
                        string sortOrderString = string.Empty;
                        int startIndex = -1;
                        for (int j = sortOrderPropertyName.Length; j < temp.Length; j++)
                        {
                            char character = temp[j];

                            if (!char.IsDigit(character) && sortOrderString.Length > 0)
                                break;

                            if (character == ' ' || character == '=')
                                continue;

                            if (char.IsDigit(character))
                            {
                                if (startIndex == -1)
                                    startIndex = j;

                                sortOrderString += character;
                            }
                        }

                        string oldString = temp.Substring(0, startIndex) + sortOrderString;
                        string newString = temp.Substring(0, startIndex) + sortOrder;
                        newContent = newContent.Replace(oldString, newString);
                        Console.WriteLine("- Changing sort order for property '{0}' from {1} to {2}", propertyName, sortOrderString, sortOrder);
                    }

                    string newClassContent = originalClassContent;
                    newClassContent = newClassContent.Replace(originalPropertyContent, newContent);
                    fileContent = fileContent.Replace(originalClassContent, newClassContent);
                    File.WriteAllText(path, fileContent);
                }
            }
        }

        private string FindFile(DirectoryInfo projectFolder, Type type, string rootNamespace)
        {
            string path = GetFilePath(projectFolder, type, rootNamespace);

            if (!string.IsNullOrEmpty(path) && File.Exists(path))
                return path;

            List<FileInfo> files = projectFolder.GetFiles("*.cs", SearchOption.AllDirectories)
                .Where(c => c.FullName.IndexOf(".aspx.cs", StringComparison.OrdinalIgnoreCase) == -1 &&
                    c.FullName.IndexOf(".aspx.designer.cs", StringComparison.OrdinalIgnoreCase) == -1 &&
                    c.FullName.IndexOf(".ascx.cs", StringComparison.OrdinalIgnoreCase) == -1 &&
                    c.FullName.IndexOf(".ascx.designer.cs", StringComparison.OrdinalIgnoreCase) == -1 &&
                    c.FullName.IndexOf(".asmx.cs", StringComparison.OrdinalIgnoreCase) == -1 &&
                    c.FullName.IndexOf(".ashx.cs", StringComparison.OrdinalIgnoreCase) == -1)
                .ToList();

            foreach (FileInfo file in files)
            {
                string content = File.ReadAllText(file.FullName);
                string nameSpace = type.FullName;
                nameSpace = string.Format("namespace {0}", nameSpace.Substring(0, nameSpace.LastIndexOf(".")));
                string searchFor = string.Format(" class {0}", type.Name);

                if (!(content.Contains(nameSpace) && content.Contains(searchFor)))
                    continue;

                string subContent = content.Substring(content.IndexOf(searchFor) + searchFor.Length);

                foreach (char character in subContent)
                {
                    if (character != ' ' && character != '\t' && character != '\r' && character != '\n' && character != '{' && character != ':')
                        break;

                    if (character == '{' || character == ':')
                        return file.FullName;
                }
            }

            return string.Empty;
        }

        private string GetFilePath(DirectoryInfo projectFolder, Type type, string rootNamespace)
        {
            string fullTypeName = type.FullName;

            if (!fullTypeName.StartsWith(rootNamespace))
                return string.Empty;

            fullTypeName = fullTypeName.Substring(rootNamespace.Length);

            string[] parts = fullTypeName.Split(new char[] { '.' });
            string path = projectFolder.FullName;

            if (!path.EndsWith("\\"))
                path += "\\";

            bool breakOut = false;

            for (int i = 0; i < parts.Length - 1; i++)
            {
                path += parts[i] + "\\";

                if (Directory.Exists(path))
                    continue;

                breakOut = true;
                break;
            }

            if (breakOut)
                return string.Empty;

            path += parts.Last() + ".cs";
            return path;
        }

        private string GetRootNameSpace(FileInfo projectFile)
        {
            string fileContent = File.ReadAllText(projectFile.FullName);
            int index = fileContent.IndexOf("<RootNamespace>") + "<RootNamespace>".Length;
            fileContent = fileContent.Substring(index);
            string rootNamespace = fileContent.Substring(0, fileContent.IndexOf("<")) + ".";
            return rootNamespace;
        }

        private int FindProperty(string fileContent, string propertyName)
        {
            string searchFor = string.Format(" {0} {{", propertyName);
            int index = fileContent.IndexOf(searchFor);

            if (index != -1)
                return index + searchFor.Length;

            searchFor = string.Format(" {0}", propertyName);
            index = fileContent.IndexOf(searchFor);

            while (index != -1)
            {
                string subContent = fileContent.Substring(index + searchFor.Length);
                int count = 0;
                foreach (char character in subContent)
                {
                    count++;
                    if (character != ' ' && character != '\t' && character != '\r' && character != '\n' && character != '{')
                        break;

                    if (character == '{')
                        return index + searchFor.Length + count;
                }

                index = fileContent.IndexOf(searchFor, index + searchFor.Length + 1);
            }

            return -1;
        }

        public class FixData
        {
            public Type Type { get; set; }
            public List<FixPropertyData> FixPropertyData = new List<FixPropertyData>();
        }

        public class FixPropertyData
        {
            public Type Type { get; set; }
            public PropertyInfo Property;
            public int SortOrder { get; set; }
            public bool Changed { get; set; }

        }
    }
}
